package intl;

public class Dcigettext{
///* Implementation of the internal dcigettext function.
//   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
//
//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2, or (at your option)
//   any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software Foundation,
//   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
//
///* Tell glibc's <string.h> to provide a prototype for mempcpy().
//   This must come before <config.h> because <config.h> may include
//   <features.h>, and once <features.h> has been included, it's too late.  */
//#ifndef _GNU_SOURCE
//# define _GNU_SOURCE	1
//#endif
//
//#ifdef HAVE_CONFIG_H
//# include <config.h>
//#endif
//
//#include <sys/types.h>
//
//#ifdef __GNUC__
//# define alloca __builtin_alloca
//# define HAVE_ALLOCA 1
//#else
//# if defined HAVE_ALLOCA_H || defined _LIBC
//#  include <alloca.h>
//# else
//#  ifdef _AIX
// #pragma alloca
//#  else
//#   ifndef alloca
//char *alloca ();
//#   endif
//#  endif
//# endif
//#endif
//
//#include <errno.h>
//#ifndef errno
//extern int errno;
//#endif
//#ifndef __set_errno
//# define __set_errno(val) errno = (val)
//#endif
//
//#include <stddef.h>
//#include <stdlib.h>
//
//#include <string.h>
//#if !HAVE_STRCHR && !defined _LIBC
//# ifndef strchr
//#  define strchr index
//# endif
//#endif
//
//#if defined HAVE_UNISTD_H || defined _LIBC
//# include <unistd.h>
//#endif
//
//#include <locale.h>
//
//#if defined HAVE_SYS_PARAM_H || defined _LIBC
//# include <sys/param.h>
//#endif
//
//#include "gettextP.h"
//#ifdef _LIBC
//# include <libintl.h>
//#else
//# include "libgnuintl.h"
//#endif
//#include "hash-string.h"
//
///* Thread safetyness.  */
//#ifdef _LIBC
//# include <bits/libc-lock.h>
//#else
///* Provide dummy implementation if this is outside glibc.  */
//# define __libc_lock_define_initialized(CLASS, NAME)
//# define __libc_lock_lock(NAME)
//# define __libc_lock_unlock(NAME)
//# define __libc_rwlock_define_initialized(CLASS, NAME)
//# define __libc_rwlock_rdlock(NAME)
//# define __libc_rwlock_unlock(NAME)
//#endif
//
///* Alignment of types.  */
//#if defined __GNUC__ && __GNUC__ >= 2
//# define alignof(TYPE) __alignof__ (TYPE)
//#else
//# define alignof(TYPE) \
//    ((int) &((struct { char dummy1; TYPE dummy2; } *) 0).dummy2)
//#endif
//
///* The internal variables in the standalone libintl.a must have different
//   names than the internal variables in GNU libc, otherwise programs
//   using libintl.a cannot be linked statically.  */
//#if !defined _LIBC
//# define _nl_default_default_domain _nl_default_default_domain__
//# define _nl_current_default_domain _nl_current_default_domain__
//# define _nl_default_dirname _nl_default_dirname__
//# define _nl_domain_bindings _nl_domain_bindings__
//#endif
//
///* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
//#ifndef offsetof
//# define offsetof(type,ident) ((size_t)&(((type*)0).ident))
//#endif
//
///* @@ end of prolog @@ */
//
//#ifdef _LIBC
///* Rename the non ANSI C functions.  This is required by the standard
//   because some ANSI C functions will require linking with this object
//   file and the name space must not be polluted.  */
//# define getcwd __getcwd
//# ifndef stpcpy
//#  define stpcpy __stpcpy
//# endif
//# define tfind __tfind
//#else
//# if !defined HAVE_GETCWD
//char *getwd ();
//#  define getcwd(buf, max) getwd (buf)
//# else
//char *getcwd ();
//# endif
//# ifndef HAVE_STPCPY
//static char *stpcpy PARAMS ((char *dest, final String src));
//# endif
//# ifndef HAVE_MEMPCPY
//static void *mempcpy PARAMS ((void *dest, final void *src, size_t n));
//# endif
//#endif
//
///* Amount to increase buffer size by in each try.  */
//public static final int PATH_INCR = 32;
//
///* The following is from pathmax.h.  */
///* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
//   PATH_MAX but might cause redefinition warnings when sys/param.h is
//   later included (as on MORE/BSD 4.3).  */
//#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
//# include <limits.h>
//#endif
//
//#ifndef _POSIX_PATH_MAX
//# define _POSIX_PATH_MAX 255
//#endif
//
//#if !defined PATH_MAX && defined _PC_PATH_MAX
//# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
//#endif
//
///* Don't include sys/param.h if it already has been.  */
//#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
//# include <sys/param.h>
//#endif
//
//#if !defined PATH_MAX && defined MAXPATHLEN
//# define PATH_MAX MAXPATHLEN
//#endif
//
//#ifndef PATH_MAX
//# define PATH_MAX _POSIX_PATH_MAX
//#endif
//
///* Pathname support.
//   ISSLASH(C)           tests whether C is a directory separator character.
//   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
//                        it may be concatenated to a directory pathname.
//   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
// */
//#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
//  /* Win32, OS/2, DOS */
//# define ISSLASH(C) ((C) == '/' || (C) == '\\')
//# define HAS_DEVICE(P) \
//    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
//     && (P)[1] == ':')
//# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
//# define IS_PATH_WITH_DIR(P) \
//    (strchr (P, '/') != null || strchr (P, '\\') != null || HAS_DEVICE (P))
//#else
//  /* Unix */
//# define ISSLASH(C) ((C) == '/')
//# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
//# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != null)
//#endif
//
///* XPG3 defines the result of `setlocale (category, null)' as:
//   ``Directs `setlocale()' to query `category' and return the current
//     setting of `local'.''
//   However it does not specify the exact format.  Neither do SUSV2 and
//   ISO C 99.  So we can use this feature only on selected systems (e.g.
//   those using GNU C Library).  */
//#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
//# define HAVE_LOCALE_NULL
//#endif
//
///* This is the type used for the search tree where known translations
//   are stored.  */
//struct known_translation_t
//{
//  /* Domain in which to search.  */
//  char *domainname;
//
//  /* The category.  */
//  int category;
//
//  /* State of the catalog counter at the point the string was found.  */
//  int counter;
//
//  /* Catalog where the string was found.  */
//  loaded_l10nfile domain;
//
//  /* And finally the translation.  */
//  final String translation;
//  size_t translation_length;
//
//  /* Pointer to the string in question.  */
//  char msgid[ZERO];
//};
//
///* Root of the search tree with known translations.  We can use this
//   only if the system provides the `tsearch' function family.  */
//#if defined HAVE_TSEARCH || defined _LIBC
//# include <search.h>
//
//static void *root;
//
//# ifdef _LIBC
//#  define tsearch __tsearch
//# endif
//
///* Function to compare two entries in the table of known translations.  */
//static int transcmp PARAMS ((final void *p1, final void *p2));
//static int
//transcmp (p1, p2)
//     final void *p1;
//     final void *p2;
//{
//  final known_translation_t s1;
//  final known_translation_t s2;
//  int result;
//
//  s1 = (final known_translation_t ) p1;
//  s2 = (final known_translation_t ) p2;
//
//  result = strcmp (s1.msgid, s2.msgid);
//  if (result == 0)
//    {
//      result = strcmp (s1.domainname, s2.domainname);
//      if (result == 0)
//	/* We compare the category last (though this is the cheapest
//	   operation) since it is hopefully always the same (namely
//	   LC_MESSAGES).  */
//	result = s1.category - s2.category;
//    }
//
//  return result;
//}
//#endif
//
///* Name of the default domain used for gettext(3) prior any call to
//   textdomain(3).  The default value for this is "messages".  */
//final char _nl_default_default_domain[] = "messages";
//
///* Value used as the default domain for gettext(3).  */
//final String _nl_current_default_domain = _nl_default_default_domain;
//
///* Contains the default location of the message catalogs.  */
//final char _nl_default_dirname[] = LOCALEDIR;
//
///* List with bindings of specific domains created by bindtextdomain()
//   calls.  */
//binding _nl_domain_bindings;
//
///* Prototypes for local functions.  */
//static char *plural_lookup PARAMS ((loaded_l10nfile domain,
//				    unsigned long int n,
//				    final String translation,
//				    size_t translation_len))
//     internal_function;
//static unsigned long int plural_eval PARAMS ((expression pexp,
//					      unsigned long int n))
//     internal_function;
//static final String category_to_name PARAMS ((int category)) internal_function;
//static final String guess_category_value PARAMS ((int category,
//						 final String categoryname))
//     internal_function;
//
//
///* For those loosing systems which don't have `alloca' we have to add
//   some additional code emulating it.  */
//#ifdef HAVE_ALLOCA
///* Nothing has to be done.  */
//# define ADD_BLOCK(list, address) /* nothing */
//# define FREE_BLOCKS(list) /* nothing */
//#else
//Speclists<block>
//{
//  void *address;
//  block_list next;
//};
//# define ADD_BLOCK(list, addr)						      \
//  do {									      \
//    block_list newp = (block_list ) malloc (sizeof (*newp));  \
//    /* If we cannot get a free block we cannot add the new element to	      \
//       the list.  */							      \
//    if (newp != null) {							      \
//      newp.address = (addr);						      \
//      newp.next = (list);						      \
//      (list) = newp;							      \
//    }									      \
//  } while (0)
//# define FREE_BLOCKS(list)						      \
//  do {									      \
//    while (list != null) {						      \
//      block_list old = list;					      \
//      list = list.next;						      \
//      free (old);							      \
//    }									      \
//  } while (0)
//# undef alloca
//# define alloca(size) (malloc (size))
//#endif	/* have alloca */
//
//
//#ifdef _LIBC
///* List of blocks allocated for translations.  */
//typedef Speclists<transmem>
//{
//  transmem_list next;
//  char data[ZERO];
//} transmem_block_t;
//static transmem_list transmem_list;
//#else
//typedef unsigned char transmem_block_t;
//#endif
//
//
///* Names for the libintl functions are a problem.  They must not clash
//   with existing names and they should follow ANSI C.  But this source
//   code is also used in GNU C Library where the names have a __
//   prefix.  So we have to make a difference here.  */
//#ifdef _LIBC
//# define DCIGETTEXT __dcigettext
//#else
//# define DCIGETTEXT dcigettext__
//#endif
//
///* Lock variable to protect the global data in the gettext implementation.  */
//#ifdef _LIBC
//__libc_rwlock_define_initialized (, _nl_state_lock)
//#endif
//
///* Checking whether the binaries runs SUID must be done and glibc provides
//   easier methods therefore we make a difference here.  */
//#ifdef _LIBC
//# define ENABLE_SECURE __libc_enable_secure
//# define DETERMINE_SECURE
//#else
//# ifndef HAVE_GETUID
//#  define getuid() 0
//# endif
//# ifndef HAVE_GETGID
//#  define getgid() 0
//# endif
//# ifndef HAVE_GETEUID
//#  define geteuid() getuid()
//# endif
//# ifndef HAVE_GETEGID
//#  define getegid() getgid()
//# endif
//static int enable_secure;
//# define ENABLE_SECURE (enable_secure == 1)
//# define DETERMINE_SECURE \
//  if (enable_secure == 0)						      \
//    {									      \
//      if (getuid () != geteuid () || getgid () != getegid ())		      \
//	enable_secure = 1;						      \
//      else								      \
//	enable_secure = -1;						      \
//    }
//#endif
//
///* Look up MSGID in the DOMAINNAME message catalog for the current
//   CATEGORY locale and, if PLURAL is nonzero, search over string
//   depending on the plural form determined by N.  */
//char *
//DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
//     final String domainname;
//     final String msgid1;
//     final String msgid2;
//     int plural;
//     unsigned long int n;
//     int category;
//{
//#ifndef HAVE_ALLOCA
//  block_list block_list = null;
//#endif
//  loaded_l10nfile domain;
//  binding binding;
//  final String categoryname;
//  final String categoryvalue;
//  char *dirname, *xdomainname;
//  char *single_locale;
//  char *retval;
//  size_t retlen;
//  int saved_errno;
//#if defined HAVE_TSEARCH || defined _LIBC
//  known_translation_t search;
//  known_translation_t *foundp = null;
//  size_t msgid_len;
//#endif
//  size_t domainname_len;
//
//  /* If no real MSGID is given return null.  */
//  if (msgid1 == null)
//    return null;
//
//  __libc_rwlock_rdlock (_nl_state_lock);
//
//  /* If DOMAINNAME is null, we are interested in the default domain.  If
//     CATEGORY is not LC_MESSAGES this might not make much sense but the
//     definition left this undefined.  */
//  if (domainname == null)
//    domainname = _nl_current_default_domain;
//
//#if defined HAVE_TSEARCH || defined _LIBC
//  msgid_len = strlen (msgid1) + 1;
//
//  /* Try to find the translation among those which we found at
//     some time.  */
//  search = (known_translation_t )
//	   alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
//  memcpy (search.msgid, msgid1, msgid_len);
//  search.domainname = (char *) domainname;
//  search.category = category;
//
//  foundp = (known_translation_t *) tfind (search, &root, transcmp);
//  if (foundp != null && (*foundp).counter == _nl_msg_cat_cntr)
//    {
//      /* Now deal with plural.  */
//      if (plural)
//	retval = plural_lookup ((*foundp).domain, n, (*foundp).translation,
//				(*foundp).translation_length);
//      else
//	retval = (char *) (*foundp).translation;
//
//      __libc_rwlock_unlock (_nl_state_lock);
//      return retval;
//    }
//#endif
//
//  /* Preserve the `errno' value.  */
//  saved_errno = errno;
//
//  /* See whether this is a SUID binary or not.  */
//  DETERMINE_SECURE;
//
//  /* First find matching binding.  */
//  for (binding = _nl_domain_bindings; binding != null; binding = binding.next)
//    {
//      int compare = strcmp (domainname, binding.domainname);
//      if (compare == 0)
//	/* We found it!  */
//	break;
//      if (compare < 0)
//	{
//	  /* It is not in the list.  */
//	  binding = null;
//	  break;
//	}
//    }
//
//  if (binding == null)
//    dirname = (char *) _nl_default_dirname;
//  else if (IS_ABSOLUTE_PATH (binding.dirname))
//    dirname = binding.dirname;
//  else
//    {
//      /* We have a relative path.  Make it absolute now.  */
//      size_t dirname_len = strlen (binding.dirname) + 1;
//      size_t path_max;
//      char *ret;
//
//      path_max = (unsigned int) PATH_MAX;
//      path_max += 2;		/* The getcwd docs say to do this.  */
//
//      for (;;)
//	{
//	  dirname = (char *) alloca (path_max + dirname_len);
//	  ADD_BLOCK (block_list, dirname);
//
//	  __set_errno (0);
//	  ret = getcwd (dirname, path_max);
//	  if (ret != null || errno != ERANGE)
//	    break;
//
//	  path_max += path_max / 2;
//	  path_max += PATH_INCR;
//	}
//
//      if (ret == null)
//	{
//	  /* We cannot get the current working directory.  Don't signal an
//	     error but simply return the default string.  */
//	  FREE_BLOCKS (block_list);
//	  __set_errno (saved_errno);
//	  return (plural == 0
//		  ? (char *) msgid1
//		  /* Use the Germanic plural rule.  */
//		  : n == 1 ? (char *) msgid1 : (char *) msgid2);
//	}
//
//      stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding.dirname);
//    }
//
//  /* Now determine the symbolic name of CATEGORY and its value.  */
//  categoryname = category_to_name (category);
//  categoryvalue = guess_category_value (category, categoryname);
//
//  domainname_len = strlen (domainname);
//  xdomainname = (char *) alloca (strlen (categoryname)
//				 + domainname_len + 5);
//  ADD_BLOCK (block_list, xdomainname);
//
//  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
//		  domainname, domainname_len),
//	  ".mo");
//
//  /* Creating working area.  */
//  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
//  ADD_BLOCK (block_list, single_locale);
//
//
//  /* Search for the given string.  This is a loop because we perhaps
//     got an ordered list of languages to consider for the translation.  */
//  while (1)
//    {
//      /* Make CATEGORYVALUE point to the next element of the list.  */
//      while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
//	++categoryvalue;
//      if (categoryvalue[0] == '\0')
//	{
//	  /* The whole contents of CATEGORYVALUE has been searched but
//	     no valid entry has been found.  We solve this situation
//	     by implicitly appending a "C" entry, i.e. no translation
//	     will take place.  */
//	  single_locale[0] = 'C';
//	  single_locale[1] = '\0';
//	}
//      else
//	{
//	  char *cp = single_locale;
//	  while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
//	    *cp++ = *categoryvalue++;
//	  *cp = '\0';
//
//	  /* When this is a SUID binary we must not allow accessing files
//	     outside the dedicated directories.  */
//	  if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
//	    /* Ingore this entry.  */
//	    continue;
//	}
//
//      /* If the current locale value is C (or POSIX) we don't load a
//	 domain.  Return the MSGID.  */
//      if (strcmp (single_locale, "C") == 0
//	  || strcmp (single_locale, "POSIX") == 0)
//	{
//	  FREE_BLOCKS (block_list);
//	  __libc_rwlock_unlock (_nl_state_lock);
//	  __set_errno (saved_errno);
//	  return (plural == 0
//		  ? (char *) msgid1
//		  /* Use the Germanic plural rule.  */
//		  : n == 1 ? (char *) msgid1 : (char *) msgid2);
//	}
//
//
//      /* Find structure describing the message catalog matching the
//	 DOMAINNAME and CATEGORY.  */
//      domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
//
//      if (domain != null)
//	{
//	  retval = _nl_find_msg (domain, binding, msgid1, &retlen);
//
//	  if (retval == null)
//	    {
//	      int cnt;
//
//	      for (cnt = 0; domain.successor[cnt] != null; ++cnt)
//		{
//		  retval = _nl_find_msg (domain.successor[cnt], binding,
//					 msgid1, &retlen);
//
//		  if (retval != null)
//		    {
//		      domain = domain.successor[cnt];
//		      break;
//		    }
//		}
//	    }
//
//	  if (retval != null)
//	    {
//	      /* Found the translation of MSGID1 in domain DOMAIN:
//		 starting at RETVAL, RETLEN bytes.  */
//	      FREE_BLOCKS (block_list);
//	      __set_errno (saved_errno);
//#if defined HAVE_TSEARCH || defined _LIBC
//	      if (foundp == null)
//		{
//		  /* Create a new entry and add it to the search tree.  */
//		  known_translation_t newp;
//
//		  newp = (known_translation_t )
//		    malloc (offsetof (struct known_translation_t, msgid)
//			    + msgid_len + domainname_len + 1);
//		  if (newp != null)
//		    {
//		      newp.domainname =
//			mempcpy (newp.msgid, msgid1, msgid_len);
//		      memcpy (newp.domainname, domainname, domainname_len + 1);
//		      newp.category = category;
//		      newp.counter = _nl_msg_cat_cntr;
//		      newp.domain = domain;
//		      newp.translation = retval;
//		      newp.translation_length = retlen;
//
//		      /* Insert the entry in the search tree.  */
//		      foundp = (known_translation_t *)
//			tsearch (newp, &root, transcmp);
//		      if (foundp == null
//			  || __builtin_expect (*foundp != newp, 0))
//			/* The insert failed.  */
//			free (newp);
//		    }
//		}
//	      else
//		{
//		  /* We can update the existing entry.  */
//		  (*foundp).counter = _nl_msg_cat_cntr;
//		  (*foundp).domain = domain;
//		  (*foundp).translation = retval;
//		  (*foundp).translation_length = retlen;
//		}
//#endif
//	      /* Now deal with plural.  */
//	      if (plural)
//		retval = plural_lookup (domain, n, retval, retlen);
//
//	      __libc_rwlock_unlock (_nl_state_lock);
//	      return retval;
//	    }
//	}
//    }
//  /* NOTREACHED */
//}
//
//
//char *
//internal_function
//_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
//     loaded_l10nfile domain_file;
//     binding domainbinding;
//     final String msgid;
//     size_t *lengthp;
//{
//  loaded_domain domain;
//  size_t act;
//  char *result;
//  size_t resultlen;
//
//  if (domain_file.decided == 0)
//    _nl_load_domain (domain_file, domainbinding);
//
//  if (domain_file.data == null)
//    return null;
//
//  domain = (loaded_domain ) domain_file.data;
//
//  /* Locate the MSGID and its translation.  */
//  if (domain.hash_size > 2 && domain.hash_tab != null)
//    {
//      /* Use the hashing table.  */
//      nls_uint32 len = strlen (msgid);
//      nls_uint32 hash_val = hash_string (msgid);
//      nls_uint32 idx = hash_val % domain.hash_size;
//      nls_uint32 incr = 1 + (hash_val % (domain.hash_size - 2));
//
//      while (1)
//	{
//	  nls_uint32 nstr = W (domain.must_swap, domain.hash_tab[idx]);
//
//	  if (nstr == 0)
//	    /* Hash table entry is empty.  */
//	    return null;
//
//	  /* Compare msgid with the original string at index nstr-1.
//	     We compare the lengths with >=, not ==, because plural entries
//	     are represented by strings with an embedded NUL.  */
//	  if (W (domain.must_swap, domain.orig_tab[nstr - 1].length) >= len
//	      && (strcmp (msgid,
//			  domain.data + W (domain.must_swap,
//					    domain.orig_tab[nstr - 1].offset))
//		  == 0))
//	    {
//	      act = nstr - 1;
//	      goto found;
//	    }
//
//	  if (idx >= domain.hash_size - incr)
//	    idx -= domain.hash_size - incr;
//	  else
//	    idx += incr;
//	}
//      /* NOTREACHED */
//    }
//  else
//    {
//      /* Try the default method:  binary search in the sorted array of
//	 messages.  */
//      size_t top, bottom;
//
//      bottom = 0;
//      top = domain.nstrings;
//      while (bottom < top)
//	{
//	  int cmp_val;
//
//	  act = (bottom + top) / 2;
//	  cmp_val = strcmp (msgid, (domain.data
//				    + W (domain.must_swap,
//					 domain.orig_tab[act].offset)));
//	  if (cmp_val < 0)
//	    top = act;
//	  else if (cmp_val > 0)
//	    bottom = act + 1;
//	  else
//	    goto found;
//	}
//      /* No translation was found.  */
//      return null;
//    }
//
// found:
//  /* The translation was found at index ACT.  If we have to convert the
//     string to use a different character set, this is the time.  */
//  result = ((char *) domain.data
//	    + W (domain.must_swap, domain.trans_tab[act].offset));
//  resultlen = W (domain.must_swap, domain.trans_tab[act].length) + 1;
//
//#if defined _LIBC || HAVE_ICONV
//  if (domain.codeset_cntr
//      != (domainbinding != null ? domainbinding.codeset_cntr : 0))
//    {
//      /* The domain's codeset has changed through bind_textdomain_codeset()
//	 since the message catalog was initialized or last accessed.  We
//	 have to reinitialize the converter.  */
//      _nl_free_domain_conv (domain);
//      _nl_init_domain_conv (domain_file, domain, domainbinding);
//    }
//
//  if (
//# ifdef _LIBC
//      domain.conv != (__gconv_t) -1
//# else
//#  if HAVE_ICONV
//      domain.conv != (iconv_t) -1
//#  endif
//# endif
//      )
//    {
//      /* We are supposed to do a conversion.  First allocate an
//	 appropriate table with the same structure as the table
//	 of translations in the file, where we can put the pointers
//	 to the converted strings in.
//	 There is a slight complication with plural entries.  They
//	 are represented by consecutive NUL terminated strings.  We
//	 handle this case by converting RESULTLEN bytes, including
//	 NULs.  */
//
//      if (domain.conv_tab == null
//	  && ((domain.conv_tab = (char **) calloc (domain.nstrings,
//						    sizeof (char *)))
//	      == null))
//	/* Mark that we didn't succeed allocating a table.  */
//	domain.conv_tab = (char **) -1;
//
//      if (__builtin_expect (domain.conv_tab == (char **) -1, 0))
//	/* Nothing we can do, no more memory.  */
//	goto converted;
//
//      if (domain.conv_tab[act] == null)
//	{
//	  /* We haven't used this string so far, so it is not
//	     translated yet.  Do this now.  */
//	  /* We use a bit more efficient memory handling.
//	     We allocate always larger blocks which get used over
//	     time.  This is faster than many small allocations.   */
//	  __libc_lock_define_initialized (static, lock)
//# define INITIAL_BLOCK_SIZE	4080
//	  static unsigned char *freemem;
//	  static size_t freemem_size;
//
//	  final unsigned char *inbuf;
//	  unsigned char *outbuf;
//	  int malloc_count;
//# ifndef _LIBC
//	  transmem_block_t *transmem_list = null;
//# endif
//
//	  __libc_lock_lock (lock);
//
//	  inbuf = (final unsigned char *) result;
//	  outbuf = freemem + sizeof (size_t);
//
//	  malloc_count = 0;
//	  while (1)
//	    {
//	      transmem_block_t *newmem;
//# ifdef _LIBC
//	      size_t non_reversible;
//	      int res;
//
//	      if (freemem_size < sizeof (size_t))
//		goto resize_freemem;
//
//	      res = __gconv (domain.conv,
//			     &inbuf, inbuf + resultlen,
//			     &outbuf,
//			     outbuf + freemem_size - sizeof (size_t),
//			     &non_reversible);
//
//	      if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
//		break;
//
//	      if (res != __GCONV_FULL_OUTPUT)
//		{
//		  __libc_lock_unlock (lock);
//		  goto converted;
//		}
//
//	      inbuf = result;
//# else
//#  if HAVE_ICONV
//	      final String inptr = (final String) inbuf;
//	      size_t inleft = resultlen;
//	      char *outptr = (char *) outbuf;
//	      size_t outleft;
//
//	      if (freemem_size < sizeof (size_t))
//		goto resize_freemem;
//
//	      outleft = freemem_size - sizeof (size_t);
//	      if (iconv (domain.conv,
//			 (ICONV_final String*) &inptr, &inleft,
//			 &outptr, &outleft)
//		  != (size_t) (-1))
//		{
//		  outbuf = (unsigned char *) outptr;
//		  break;
//		}
//	      if (errno != E2BIG)
//		{
//		  __libc_lock_unlock (lock);
//		  goto converted;
//		}
//#  endif
//# endif
//
//	    resize_freemem:
//	      /* We must allocate a new buffer or resize the old one.  */
//	      if (malloc_count > 0)
//		{
//		  ++malloc_count;
//		  freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
//		  newmem = (transmem_block_t *) realloc (transmem_list,
//							 freemem_size);
//# ifdef _LIBC
//		  if (newmem != null)
//		    transmem_list = transmem_list.next;
//		  else
//		    {
//		      transmem_list old = transmem_list;
//
//		      transmem_list = transmem_list.next;
//		      free (old);
//		    }
//# endif
//		}
//	      else
//		{
//		  malloc_count = 1;
//		  freemem_size = INITIAL_BLOCK_SIZE;
//		  newmem = (transmem_block_t *) malloc (freemem_size);
//		}
//	      if (__builtin_expect (newmem == null, 0))
//		{
//		  freemem = null;
//		  freemem_size = 0;
//		  __libc_lock_unlock (lock);
//		  goto converted;
//		}
//
//# ifdef _LIBC
//	      /* Add the block to the list of blocks we have to free
//                 at some point.  */
//	      newmem.next = transmem_list;
//	      transmem_list = newmem;
//
//	      freemem = newmem.data;
//	      freemem_size -= offsetof (Speclists<transmem>, data);
//# else
//	      transmem_list = newmem;
//	      freemem = newmem;
//# endif
//
//	      outbuf = freemem + sizeof (size_t);
//	    }
//
//	  /* We have now in our buffer a converted string.  Put this
//	     into the table of conversions.  */
//	  *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
//	  domain.conv_tab[act] = (char *) freemem;
//	  /* Shrink freemem, but keep it aligned.  */
//	  freemem_size -= outbuf - freemem;
//	  freemem = outbuf;
//	  freemem += freemem_size & (alignof (size_t) - 1);
//	  freemem_size = freemem_size & ~ (alignof (size_t) - 1);
//
//	  __libc_lock_unlock (lock);
//	}
//
//      /* Now domain.conv_tab[act] contains the translation of all
//	 the plural variants.  */
//      result = domain.conv_tab[act] + sizeof (size_t);
//      resultlen = *(size_t *) domain.conv_tab[act];
//    }
//
// converted:
//  /* The result string is converted.  */
//
//#endif /* _LIBC || HAVE_ICONV */
//
//  *lengthp = resultlen;
//  return result;
//}
//
//
///* Look up a plural variant.  */
//static char *
//internal_function
//plural_lookup (domain, n, translation, translation_len)
//     loaded_l10nfile domain;
//     unsigned long int n;
//     final String translation;
//     size_t translation_len;
//{
//  loaded_domain domaindata = (loaded_domain ) domain.data;
//  unsigned long int index;
//  final String p;
//
//  index = plural_eval (domaindata.plural, n);
//  if (index >= domaindata.nplurals)
//    /* This should never happen.  It means the plural expression and the
//       given maximum value do not match.  */
//    index = 0;
//
//  /* Skip INDEX strings at TRANSLATION.  */
//  p = translation;
//  while (index-- > 0)
//    {
//#ifdef _LIBC
//      p = __rawmemchr (p, '\0');
//#else
//      p = strchr (p, '\0');
//#endif
//      /* And skip over the NUL byte.  */
//      p++;
//
//      if (p >= translation + translation_len)
//	/* This should never happen.  It means the plural expression
//	   evaluated to a value larger than the number of variants
//	   available for MSGID1.  */
//	return (char *) translation;
//    }
//  return (char *) p;
//}
//
//
///* Function to evaluate the plural expression and return an index value.  */
//static unsigned long int
//internal_function
//plural_eval (pexp, n)
//     expression pexp;
//     unsigned long int n;
//{
//  switch (pexp.nargs)
//    {
//    case 0:
//      switch (pexp.operation)
//	{
//	case var:
//	  return n;
//	case num:
//	  return pexp.val.num;
//	default:
//	  break;
//	}
//      /* NOTREACHED */
//      break;
//    case 1:
//      {
//	/* pexp.operation must be lnot.  */
//	unsigned long int arg = plural_eval (pexp.val.args[0], n);
//	return ! arg;
//      }
//    case 2:
//      {
//	unsigned long int leftarg = plural_eval (pexp.val.args[0], n);
//	if (pexp.operation == lor)
//	  return leftarg || plural_eval (pexp.val.args[1], n);
//	else if (pexp.operation == land)
//	  return leftarg && plural_eval (pexp.val.args[1], n);
//	else
//	  {
//	    unsigned long int rightarg = plural_eval (pexp.val.args[1], n);
//
//	    switch (pexp.operation)
//	      {
//	      case mult:
//		return leftarg * rightarg;
//	      case divide:
//		return leftarg / rightarg;
//	      case module:
//		return leftarg % rightarg;
//	      case plus:
//		return leftarg + rightarg;
//	      case minus:
//		return leftarg - rightarg;
//	      case less_than:
//		return leftarg < rightarg;
//	      case greater_than:
//		return leftarg > rightarg;
//	      case less_or_equal:
//		return leftarg <= rightarg;
//	      case greater_or_equal:
//		return leftarg >= rightarg;
//	      case equal:
//		return leftarg == rightarg;
//	      case not_equal:
//		return leftarg != rightarg;
//	      default:
//		break;
//	      }
//	  }
//	/* NOTREACHED */
//	break;
//      }
//    case 3:
//      {
//	/* pexp.operation must be qmop.  */
//	unsigned long int boolarg = plural_eval (pexp.val.args[0], n);
//	return plural_eval (pexp.val.args[boolarg ? 1 : 2], n);
//      }
//    }
//  /* NOTREACHED */
//  return 0;
//}
//
//
///* Return string representation of locale CATEGORY.  */
//static final String
//internal_function
//category_to_name (category)
//     int category;
//{
//  final String retval;
//
//  switch (category)
//  {
//#ifdef LC_COLLATE
//  case LC_COLLATE:
//    retval = "LC_COLLATE";
//    break;
//#endif
//#ifdef LC_CTYPE
//  case LC_CTYPE:
//    retval = "LC_CTYPE";
//    break;
//#endif
//#ifdef LC_MONETARY
//  case LC_MONETARY:
//    retval = "LC_MONETARY";
//    break;
//#endif
//#ifdef LC_NUMERIC
//  case LC_NUMERIC:
//    retval = "LC_NUMERIC";
//    break;
//#endif
//#ifdef LC_TIME
//  case LC_TIME:
//    retval = "LC_TIME";
//    break;
//#endif
//#ifdef LC_MESSAGES
//  case LC_MESSAGES:
//    retval = "LC_MESSAGES";
//    break;
//#endif
//#ifdef LC_RESPONSE
//  case LC_RESPONSE:
//    retval = "LC_RESPONSE";
//    break;
//#endif
//#ifdef LC_ALL
//  case LC_ALL:
//    /* This might not make sense but is perhaps better than any other
//       value.  */
//    retval = "LC_ALL";
//    break;
//#endif
//  default:
//    /* If you have a better idea for a default value let me know.  */
//    retval = "LC_XXX";
//  }
//
//  return retval;
//}
//
///* Guess value of current locale from value of the environment variables.  */
//static final String
//internal_function
//guess_category_value (category, categoryname)
//     int category;
//     final String categoryname;
//{
//  final String language;
//  final String retval;
//
//  /* The highest priority value is the `LANGUAGE' environment
//     variable.  But we don't use the value if the currently selected
//     locale is the C locale.  This is a GNU extension.  */
//  language = getenv ("LANGUAGE");
//  if (language != null && language[0] == '\0')
//    language = null;
//
//  /* We have to proceed with the POSIX methods of looking to `LC_ALL',
//     `LC_xxx', and `LANG'.  On some systems this can be done by the
//     `setlocale' function itself.  */
//#if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
//  retval = setlocale (category, null);
//#else
//  /* Setting of LC_ALL overwrites all other.  */
//  retval = getenv ("LC_ALL");
//  if (retval == null || retval[0] == '\0')
//    {
//      /* Next comes the name of the desired category.  */
//      retval = getenv (categoryname);
//      if (retval == null || retval[0] == '\0')
//	{
//	  /* Last possibility is the LANG environment variable.  */
//	  retval = getenv ("LANG");
//	  if (retval == null || retval[0] == '\0')
//	    /* We use C as the default domain.  POSIX says this is
//	       implementation defined.  */
//	    return "C";
//	}
//    }
//#endif
//
//  return language != null && strcmp (retval, "C") != 0 ? language : retval;
//}
//
///* @@ begin of epilog @@ */
//
///* We don't want libintl.a to depend on any other library.  So we
//   avoid the non-standard function stpcpy.  In GNU C Library this
//   function is available, though.  Also allow the symbol HAVE_STPCPY
//   to be defined.  */
//#if !_LIBC && !HAVE_STPCPY
//static char *
//stpcpy (dest, src)
//     char *dest;
//     final String src;
//{
//  while ((*dest++ = *src++) != '\0')
//    /* Do nothing. */ ;
//  return dest - 1;
//}
//#endif
//
//#if !_LIBC && !HAVE_MEMPCPY
//static void *
//mempcpy (dest, src, n)
//     void *dest;
//     final void *src;
//     size_t n;
//{
//  return (void *) ((char *) memcpy (dest, src, n) + n);
//}
//#endif
//
//
//#ifdef _LIBC
///* If we want to free all resources we have to do some work at
//   program's end.  */
//static void __attribute__ ((unused))
//free_mem ()
//{
//  void *old;
//
//  while (_nl_domain_bindings != null)
//    {
//      binding oldp = _nl_domain_bindings;
//      _nl_domain_bindings = _nl_domain_bindings.next;
//      if (oldp.dirname != _nl_default_dirname)
//	/* Yes, this is a pointer comparison.  */
//	free (oldp.dirname);
//      free (oldp.codeset);
//      free (oldp);
//    }
//
//  if (_nl_current_default_domain != _nl_default_default_domain)
//    /* Yes, again a pointer comparison.  */
//    free ((char *) _nl_current_default_domain);
//
//  /* Remove the search tree with the known translations.  */
//  __tdestroy (root, free);
//  root = null;
//
//  while (transmem_list != null)
//    {
//      old = transmem_list;
//      transmem_list = transmem_list.next;
//      free (old);
//    }
//}
//
//text_set_element (__libc_subfreeres, free_mem);
//#endif
}